<template>
  <div class="stopword-tab">
    <TabScaffold :current="page" :pageSize="pageSize" :total="total" :pageCount="pageData.length" :checkAll="checkAll"
      :pageSizeOptions="['10', '20', '25', '50']" @update:current="onPageChange" @update:pageSize="onPageSizeChange"
      @check-all="onCheckAll">
      <!-- 工具栏：左侧 -->
      <template #toolbar-left>
        <a-space>
          <a-button @click="onAdd">新增</a-button>
          <a-button :disabled="!selectedRowKeys.length" danger @click="confirmBatchDelete">批量删除</a-button>
          <a-button @click="onOpenImport">导入</a-button>
          <a-button :loading="exporting" @click="onOpenExport">导出</a-button>
        </a-space>
      </template>

      <!-- 工具栏：右侧 -->
      <template #toolbar-right>
        <a-input-search v-model:value="keyword" placeholder="输入停用词搜索" enter-button="搜索" allow-clear style="width: 260px"
          @search="onSearch" />
      </template>

      <!-- 表格 -->
      <a-table class="row40" :columns="columns" :data-source="pageData" :loading="loading" row-key="id"
        :pagination="false" :row-selection="rowSelection" bordered :customRow="onCustomRow">
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'query'">
            <!-- 改为纯文本（黑色），不再点击名称跳转 -->
            <span class="query-text">{{ record.query }}</span>
          </template>

          <!-- 状态 -->
          <template v-else-if="column.key === 'status'">
            <span class="status-text" :class="record.status === 'published' ? 'ok' : 'off'">
              {{ record.status === "published" ? "启用" : "停用" }}
            </span>
          </template>

          <!-- 操作 -->
          <template v-else-if="column.key === 'actions'">
            <a-button type="link" class="op-link" @click="toEdit(record)">编辑</a-button>
            <span class="op-sep">|</span>
            <a-button type="link" danger class="op-link" @click="confirmSingleDelete(record)">删除</a-button>
            <span class="op-sep">|</span>
            <a-button type="link" class="op-link" :disabled="record.status !== 'published'"
              @click="onDisable(record)">停用</a-button>
            <span class="op-sep">|</span>
            <a-button type="link" class="op-link" :disabled="record.status === 'published'"
              @click="onEnable(record)">启用</a-button>
          </template>
        </template>
      </a-table>
    </TabScaffold>

    <!-- 导入 / 导出弹窗 -->
    <ImportModal v-model="importVisible" title="停用词导入" tip="说明：支持 CSV 或 JSON（UTF-8）。" @import="handleImport" />
    <ExportModal v-model="exportVisible" v-model:format="exportFormat" :loading="exporting" title="停用词导出"
      @confirm="handleExport" />
  </div>
</template>

<script setup lang="ts">
import { h, onMounted, ref, computed } from "vue";
import { useRouter, useRoute } from "vue-router";
import type { TableColumnsType } from "ant-design-vue";
import { message, Modal } from "ant-design-vue";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";

import TabScaffold from "@/components/TabScaffold.vue";
import ImportModal from "@/components/ImportModal.vue";
import ExportModal from "@/components/ExportModal.vue";

import {
  fetchStopwordList,
  batchRemoveStopwords,
  removeStopword,
  createStopword,
  updateStopword,
  importStopwordsByFile,
  fetchStopwordsForExport,
  type StopwordItem,
} from "@/api/modules/stopwords.api";

const router = useRouter();
const route = useRoute();

/** 列表与分页 */
const loading = ref(false);
const keyword = ref("");
const page = ref(1);
const pageSize = ref(10);
const total = ref(0);
const data = ref<StopwordItem[]>([]);
const pageData = computed(() => data.value);

/** 选择 */
const selectedRowKeys = ref<Array<number | string>>([]);
const checkAll = computed(() => pageData.value.length > 0 && selectedRowKeys.value.length === pageData.value.length);
const rowSelection = computed(() => ({
  selectedRowKeys: selectedRowKeys.value,
  onChange: (keys: (string | number)[]) => (selectedRowKeys.value = keys as Array<number | string>),
}));

/** 表头 */
const columns = ref<TableColumnsType>([
  { title: "名称", dataIndex: "query", key: "query" },
  { title: "状态", dataIndex: "status", key: "status", width: 120 },
  { title: "操作", key: "actions", width: 260 },
]) as any;

async function loadList() {
  loading.value = true;
  try {
    let tries = 0;
    while (true) {
      const res = await fetchStopwordList({
        page: page.value,
        pageSize: pageSize.value,
        keyword: keyword.value.trim(),
        sort: ["id"],
        excludeStatus: "archived",
      });

      if (page.value > 1 && (!res.list || res.list.length === 0)) {
        page.value = page.value - 1;
        tries++;
        if (tries <= 3) continue;
      }

      data.value = res.list;
      total.value = res.total;
      break;
    }
  } finally {
    loading.value = false;
  }
}

function onSearch() {
  page.value = 1;
  loadList();
}
function onPageChange(p: number) {
  page.value = p;
  selectedRowKeys.value = [];
  loadList();
}
/** 切换每页数量 */
function onPageSizeChange(size: number) {
  pageSize.value = Number(size);
  page.value = 1;
  selectedRowKeys.value = [];
  loadList();
}
function onCheckAll(ev: any) {
  const checked = ev?.target?.checked ?? false;
  selectedRowKeys.value = checked ? pageData.value.map((x) => x.id) : [];
}

/** ===== Tab的返回地址===== */
const currentAsRet = () => route.fullPath;

/** 跳转 */
function onAdd() {
  router.push({ path: "/stopwordListTabPage", query: { ret: currentAsRet() } });
}
function toEdit(record: StopwordItem) {
  router.push({
    path: "/stopwordListTabPage",
    query: { id: String(record.id), ret: currentAsRet() },
  });
}
function toInfo(record: StopwordItem) {
  router.push({
    path: "/stopwordListTabInfo",
    query: { id: String(record.id), ret: currentAsRet() },
  });
}

/** 整行点击（操作区域除外） */
function onCustomRow(record: StopwordItem) {
  return {
    onClick: (e: MouseEvent) => {
      const el = e.target as HTMLElement;
      if (el.closest(".op-link") || el.closest(".ant-btn") || el.closest(".ant-checkbox-wrapper") || el.closest(".ant-checkbox")) {
        return;
      }
      toInfo(record);
    },
    style: { cursor: "pointer" },
  } as any;
}

/** 删除 */
function confirmSingleDelete(record: StopwordItem) {
  Modal.confirm({
    title: "确认删除该记录？",
    content: `将删除：${record.id}`,
    okText: "删除",
    cancelText: "取消",
    okType: "danger",
    async onOk() {
      await removeStopword(record.id);
      message.success("删除成功");
      await loadList();
    },
  });
}

/** 批量删除确认 */
function confirmBatchDelete() {
  if (!selectedRowKeys.value.length) return;
  const ids = selectedRowKeys.value.slice();
  Modal.confirm({
    title: "确认删除所选记录？",
    icon: h(ExclamationCircleOutlined, { style: "color:#faad14" }),
    content: `将删除：${ids.join(", ")}（共 ${ids.length} 条）`,
    okText: "删除",
    cancelText: "取消",
    centered: true,
    maskClosable: false,
    okButtonProps: { danger: true },
    async onOk() {
      await batchRemoveStopwords(ids);
      message.success("删除成功");
      selectedRowKeys.value = [];
      await loadList();
    },
  });
}

/** 启用 / 停用 */
async function onEnable(record: StopwordItem) {
  if (record.status === "published") return;
  await updateStopword(record.id, { status: "published" });
  message.success("已启用");
  loadList();
}
async function onDisable(record: StopwordItem) {
  if (record.status !== "published") return;
  await updateStopword(record.id, { status: "draft" });
  message.success("已停用");
  loadList();
}

/** 导入 */
const importVisible = ref(false);
function onOpenImport() {
  importVisible.value = true;
}
async function handleImport(file: File) {
  try {
    const stat = await importStopwordsByFile(file);
    const inserted = Number(stat?.inserted ?? stat?.created ?? 0);
    const updated = Number(stat?.updated ?? 0);
    const skipped = Number(stat?.skipped ?? stat?.failed ?? 0);
    const total = stat?.total ?? inserted + updated + skipped;
    const pieces: string[] = [];
    if (typeof total !== "undefined") pieces.push(``);
    pieces.push(``);
    if (updated) pieces.push(`更新 ${updated}`);
    if (skipped) pieces.push(`跳过 ${skipped}`);
    message.success(`导入成功`);
    importVisible.value = false;
    loadList();
  } catch (e: any) {
    const code =
      e?.response?.data?.errors?.[0]?.extensions?.code ||
      e?.data?.errors?.[0]?.extensions?.code ||
      e?.code;
    if (code === "RECORD_NOT_UNIQUE") {
      message.error("检测到重复的值");
      return;
    }

    try {
      const text = await file.text();
      let items: Array<{ query: string; status?: "published" | "draft" }> = [];
      if (file.type.includes("json") || /\.json$/i.test(file.name)) {
        const parsed = JSON.parse(text);
        if (Array.isArray(parsed)) {
          items = parsed.map((x) => ({
            query: String(x.query ?? "").trim(),
            status: (x.status as any) || "published",
          }));
        }
      } else {
        const lines = text.split(/\r?\n/).filter((l) => l.trim().length);
        if (!lines.length) throw new Error("CSV 内容为空");
        const header = lines[0].split(",").map((s) => s.trim().toLowerCase());
        const qi = header.indexOf("query");
        const si = header.indexOf("status");
        if (qi === -1) throw new Error("CSV 缺少表头字段 query");
        for (let i = 1; i < lines.length; i++) {
          const cols = lines[i].split(",").map((s) => s.trim());
          const query = (cols[qi] || "").trim();
          const status = (si >= 0 ? (cols[si] || "").trim() : "") as any;
          if (query) items.push({ query, status: (status || "published") as any });
        }
      }
      items = items.filter((x) => x.query);
      if (!items.length) throw new Error("未解析到有效记录");
      await Promise.all(
        items.map((it) => createStopword({ query: it.query, status: it.status || "published" }))
      );
      message.success(`导入成功`);
      importVisible.value = false;
      loadList();
    } catch (err: any) {
      message.error(`导入失败：${err?.message || err}`);
    }
  }
}

/** 导出 */
const exportVisible = ref(false);
const exporting = ref(false);
const exportFormat = ref<"csv" | "json">("csv");
function onOpenExport() {
  exportVisible.value = true;
}
async function handleExport(fmt: "csv" | "json") {
  exporting.value = true;
  try {
    const ids = (selectedRowKeys.value as Array<number | string>) ?? [];
    const rows = await fetchStopwordsForExport({
      ids: ids.length ? ids : undefined,
      excludeStatus: "archived",
      sort: "id",
    });

    if (fmt === "json") {
      const blob = new Blob([JSON.stringify(rows, null, 2)], {
        type: "application/json;charset=utf-8",
      });
      downloadBlob(blob, buildFileName("json"));
    } else {
      const header = "query,status";
      const lines = rows.map((r) => `${safeCsv(r.query)},${r.status}`);
      const csv = [header, ...lines].join("\n");
      const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
      downloadBlob(blob, buildFileName("csv"));
    }

    exportVisible.value = false;
    message.success("导出成功");
  } catch (e: any) {
    message.error(`导出失败：${e?.message || e}`);
  } finally {
    exporting.value = false;
  }
}

/* ===== 工具 ===== */
function safeCsv(s: string) {
  if (s == null) return "";
  const needQuote = /[",\n]/.test(s);
  const body = String(s).replace(/"/g, '""');
  return needQuote ? `"${body}"` : body;
}
function downloadBlob(blob: Blob, filename: string) {
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = filename;
  a.click();
  URL.revokeObjectURL(url);
}
function buildFileName(ext: "csv" | "json") {
  const d = new Date();
  const ts = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}_${String(
    d.getHours()
  ).padStart(2, "0")}${String(d.getMinutes()).padStart(2, "0")}${String(d.getSeconds()).padStart(2, "0")}`;
  return `stopwords_${ts}.${ext}`;
}

onMounted(loadList);
</script>

<style scoped>
/* 表头单元格 */
.row40 :deep(.ant-table-thead > tr > th) {
  padding-top: 0 !important;
  padding-bottom: 0 !important;
  height: 40px !important;
  line-height: 40px !important;
  white-space: nowrap !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
}

/* 表体单元格 */
.row40 :deep(.ant-table-tbody > tr > td) {
  padding-top: 0 !important;
  padding-bottom: 0 !important;
  height: 40px !important;
  line-height: 40px !important;
  white-space: nowrap !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
}

/* 选择列 */
.row40 :deep(.ant-table-selection-column) {
  padding-top: 0 !important;
  padding-bottom: 0 !important;
  height: 40px !important;
  line-height: 40px !important;
}

/* 防止任何内层包裹再把高度撑开 */
.row40 :deep(.ant-table-cell > *:not(.ant-btn)) {
  line-height: 40px;
}

/* 行本身 */
.row40 :deep(.ant-table-tbody > tr),
.row40 :deep(.ant-table-thead > tr) {
  height: 40px !important;
}

/* 链接 / 操作按钮的微调 */
.op-link {
  padding: 0;
}

.op-sep {
  color: #999;
  margin: 0 6px;
}

.status-text.ok {
  color: #1f7a1f;
}

.status-text.off {
  color: #999999;
}

/* 名称列：改为黑色文本 */
.query-text {
  color: #000;
}

</style>
